home *** CD-ROM | disk | FTP | other *** search
/ Aminet 8 / Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso / Aminet / dev / c / mkid.lha / src / lid.c < prev    next >
C/C++ Source or Header  |  1995-06-29  |  19KB  |  1,007 lines

  1. static char copyright[] = "@(#)Copyright (c) 1986, Greg McGary";
  2. static char sccsid[] = "@(#)lid.c    1.4 86/11/06";
  3.  
  4. #include    "bool.h"
  5. #include    <stdio.h>
  6. #include    "string.h"
  7. #include    <ctype.h>
  8. #include    "radix.h"
  9. #include    "id.h"
  10. #include    "bitops.h"
  11. #include    "extern.h"
  12. #ifdef AMIGA
  13. #include    <dos.h>
  14. #endif
  15.  
  16. #ifdef REGEX
  17. extern char *regex();
  18. extern char *regcmp();
  19. #endif
  20. #ifdef RE_EXEC
  21. extern char *re_comp();
  22. extern int re_exec();
  23. #endif
  24.  
  25. #ifdef AMIGA
  26. int case_sensitive = TRUE;
  27.  
  28. char *
  29. regex(char *pattern,char *string)
  30. {
  31.     BOOL result;
  32.  
  33.     if(case_sensitive)
  34.         result = MatchPattern(pattern,string);
  35.     else
  36.         result = MatchPatternNoCase(pattern,string);
  37.  
  38.     if(result)
  39.         return(string);
  40.     else
  41.         return(NULL);
  42. }
  43.  
  44. char *
  45. regcmp(char *pattern,int dummy)
  46. {
  47.     static char *patbuf;
  48.     static int patbuflen;
  49.  
  50.     int len = strlen(pattern);
  51.  
  52.     if(len > patbuflen)
  53.     {
  54.         if(patbuf)
  55.             free(patbuf);
  56.  
  57.         if(patbuf = malloc(2 * len + 2))
  58.             patbuflen = 2 * len + 2;
  59.         else
  60.         {
  61.             patbuflen = 0;
  62.  
  63.             return(NULL);
  64.         }
  65.     }
  66.  
  67.     if(case_sensitive)
  68.     {
  69.         if(ParsePattern(pattern,patbuf,patbuflen) == -1)
  70.             return(NULL);
  71.     }
  72.     else
  73.     {
  74.         if(ParsePatternNoCase(pattern,patbuf,patbuflen) == -1)
  75.             return(NULL);
  76.     }
  77.  
  78.     return(patbuf);
  79. }
  80.  
  81. #define REGEX 1
  82. #endif
  83.  
  84. bool isMagic();
  85. char **bitsToArgv();
  86. char *fileRE();
  87. char *strcpos();
  88. int skipToArgv();
  89. int findAnchor();
  90. int findApropos();
  91. #if REGEX || RE_EXEC
  92. int findRegExp();
  93. #endif
  94. int findNonUnique();
  95. int findNumber();
  96. int findPlain();
  97. int idCompare();
  98. long searchName();
  99. void editId();
  100. void grepId();
  101. void lookId();
  102.  
  103. #ifdef USG
  104. #define    TOLOWER(c)    (isupper(c) ? _tolower(c) : (c))
  105. #else
  106. #define    TOLOWER(c)    (isupper(c) ? tolower(c) : (c))
  107. #endif
  108.  
  109. /*
  110. *  Sorry about all the globals, but it's really cleaner this way.
  111. */
  112. FILE        *IdFILE;
  113. bool        Merging;
  114. bool        Radix;
  115. char        *IdDir;
  116. long        AnchorOffset;
  117. int        BitArraySize;
  118. struct idhead    Idh;
  119. struct idarg    *IdArgs;
  120. int        (*FindFunc)() = NULL;
  121. int        Solo = 0;
  122. #define    IGNORE_SOLO(buf) \
  123. ( \
  124.        (Solo == '-' && !(ID_FLAGS(buf) & IDN_SOLO)) \
  125.     || (Solo == '+' &&  (ID_FLAGS(buf) & IDN_SOLO)) \
  126. )
  127.  
  128. char *MyName;
  129. static void
  130. usage()
  131. {
  132.     fprintf(stderr, "Usage: %s [-f<file>] [-u<n>] [-mewdoxasi] patterns...\n", MyName);
  133.     exit(1);
  134. }
  135. main(argc, argv)
  136.     int        argc;
  137.     char        **argv;
  138. {
  139.     char        *idFile = IDFILE;
  140.     char        *arg;
  141.     long        val;
  142.     void        (*doit)();
  143.     bool        forceMerge = FALSE;
  144.     int        uniqueLimit = 0;
  145.     int        op;
  146.  
  147.     MyName = basename(GETARG(argc, argv));
  148.  
  149.     while (argc) {
  150.         arg = GETARG(argc, argv);
  151.         switch (op = *arg++)
  152.         {
  153.         case '-':
  154.         case '+':
  155.             break;
  156.         default:
  157.             UNGETARG(argc, argv);
  158.             goto argsdone;
  159.         }
  160.         while (*arg) switch (*arg++)
  161.         {
  162.         case 'f': idFile = arg; goto nextarg;
  163.         case 'u': uniqueLimit = stoi(arg); goto nextarg;
  164.         case 'm': forceMerge = TRUE; break;
  165. #if REGEX || RE_EXEC
  166.         case 'e': FindFunc = findRegExp; break;
  167. #endif
  168.         case 'w': FindFunc = findPlain; break;
  169.         case 'd': Radix |= RADIX_DEC; break;
  170.         case 'o': Radix |= RADIX_OCT; break;
  171.         case 'x': Radix |= RADIX_HEX; break;
  172.         case 'a': Radix |= RADIX_ALL; break;
  173.         case 's': Solo = op; break;
  174.         case 'i': case_sensitive = FALSE; break;    // To do case-insensitive regexp stuff  -olsen
  175.         default:
  176.             usage();
  177.         }
  178.     nextarg:;
  179.     }
  180. argsdone:
  181.  
  182.     IdDir = getDirToName(idFile);
  183.     idFile = spanPath(IdDir, idFile);
  184.     if ((IdFILE = initID(idFile, &Idh, &IdArgs)) == NULL) {
  185.         filerr("open", idFile);
  186.         exit(1);
  187.     }
  188.     BitArraySize = (Idh.idh_pthc + 7) >> 3;
  189.  
  190.     switch (tolower(MyName[0]))
  191.     {
  192.     case 'a':
  193.         FindFunc = findApropos;
  194.         /*FALLTHROUGH*/
  195.     case 'l':
  196.         doit = lookId;
  197.         break;
  198.     case 'g':
  199.         doit = grepId;
  200.         break;
  201.     case 'e':
  202.         doit = editId;
  203.         break;
  204.     default:
  205.         MyName = "[alge]id";
  206.         usage();
  207.     }
  208.  
  209.     if (argc == 0) {
  210.         UNGETARG(argc, argv);
  211. #ifdef AMIGA
  212.         *argv = "";
  213. #endif
  214. #ifdef UNIX
  215.         *argv = ".";
  216. #endif
  217.     }
  218.  
  219.     while (argc) {
  220.         arg = GETARG(argc, argv);
  221.         if (FindFunc)
  222.             ;
  223.         else if ((radix(arg)) && (val = stoi(arg)) >= 0)
  224.             FindFunc = findNumber;
  225. #if REGEX || RE_EXEC
  226.         else if (isMagic(arg))
  227.             FindFunc = findRegExp;
  228. #endif
  229.         else if (arg[0] == '^')
  230.             FindFunc = findAnchor;
  231.         else
  232.             FindFunc = findPlain;
  233.  
  234.         if ((doit == lookId && !forceMerge)
  235.         || (FindFunc == findNumber && bitCount(Radix) > 1 && val > 7))
  236.             Merging = FALSE;
  237.         else
  238.             Merging = TRUE;
  239.  
  240.         if (uniqueLimit) {
  241.             if (!findNonUnique(uniqueLimit, doit))
  242.                 fprintf(stderr, "All identifiers are unique within the first %d characters\n", uniqueLimit);
  243.             exit(0);
  244.         } else if (!(*FindFunc)(arg, doit)) {
  245.             fprintf(stderr, "%s: not found\n", arg);
  246.             continue;
  247.         }
  248.     }
  249.     exit(0);
  250. }
  251.  
  252. void
  253. lookId(name, argv)
  254.     char        *name;
  255.     register char    **argv;
  256. {
  257.     register char    *arg;
  258.     register bool    crunching = FALSE;
  259.     register char    *dir;
  260.  
  261.     printf("%-14s ", name);
  262.     while (*argv) {
  263.         arg = *argv++;
  264.         if (*argv && canCrunch(arg, *argv)) {
  265. #ifdef AMIGA
  266.             if (crunching)
  267. //                printf(",%s", rootName(arg));
  268.                 printf("|%s", rootName(arg));
  269.             else if ((dir = dirname(arg)) != NULL) {
  270.                 if (*dir == '\0')
  271. //                    printf("{%s", rootName(arg));
  272.                     printf("(%s", rootName(arg));
  273.                 else
  274.                     printf("%s%s%s",dir,
  275.                        dir[strlen(dir)-1] == ':' ? "" : "/",
  276.                        rootName(arg));
  277.             }
  278. #endif
  279. #ifdef UNIX
  280.             if (crunching)
  281.                 printf(",%s", rootName(arg));
  282.             else if ((dir = dirname(arg)) && dir[0] == '.' &&
  283.                  dir[1] == '\0')
  284.                 printf("{%s", rootName(arg));
  285.             else
  286.                 printf("%s/{%s", dir, rootName(arg));
  287. #endif
  288.             /*}}*/
  289.             crunching = TRUE;
  290.         } else {
  291.             if (crunching) /*{*/
  292. #ifdef AMIGA
  293. //                printf(",%s}%s", rootName(arg), suffName(arg));
  294.                 printf("|%s)%s", rootName(arg), suffName(arg));
  295. #else
  296.                 printf(",%s}%s", rootName(arg), suffName(arg));
  297. #endif
  298.             else
  299.                 fputs(arg, stdout);
  300.             crunching = FALSE;
  301.             if (*argv)
  302.                 putchar(' ');
  303.         }
  304.     }
  305.     putchar('\n');
  306. }
  307.  
  308. void
  309. grepId(name, argv)
  310.     char        *name;
  311.     char        **argv;
  312. {
  313.     FILE        *gidFILE;
  314.     char        *gidName;
  315.     char        buf[BUFSIZ];
  316.     char        *delimit = "[^a-zA-Z0-9_]";
  317.     char        *re;
  318.     char        *reCompiled;
  319.     int        lineNumber;
  320.  
  321.     if (!Merging || (re = fileRE(name, delimit, delimit)) == NULL)
  322.         re = NULL;
  323. #ifdef REGEX
  324.     else if ((reCompiled = regcmp(re, 0)) == NULL) {
  325.         fprintf(stderr, "%s: Syntax Error: %s\n", MyName, re);
  326.         return;
  327.     }
  328. #endif
  329. #ifdef RE_EXEC
  330.     else if ((reCompiled = re_comp(re)) != NULL) {
  331.         fprintf(stderr, "%s: Syntax Error: %s (%s)\n", MyName, re, reCompiled);
  332.         return;
  333.     }
  334. #endif
  335.  
  336.     buf[0] = ' ';    /* sentry */
  337.     while (*argv) {
  338.         if ((gidFILE = fopen(gidName = *argv++, "r")) == NULL) {
  339.             filerr("open", gidName);
  340.             continue;
  341.         }
  342.         lineNumber = 0;
  343.         while (fgets(&buf[1], sizeof(buf), gidFILE)) {
  344.             lineNumber++;
  345.             if (re) {
  346. #ifdef REGEX
  347.                 if (regex(reCompiled, buf) == NULL)
  348. #endif
  349. #ifdef RE_EXEC
  350.                 if (!re_exec(buf))
  351. #endif
  352.                     continue;
  353.             } else if (!wordMatch(name, buf))
  354.                 continue;
  355.             printf("%s:%d: %s", gidName, lineNumber, &buf[1]);
  356.         }
  357.         fclose(gidFILE);
  358.     }
  359. }
  360.  
  361. void
  362. editId(name, argv)
  363.     char        *name;
  364.     char        **argv;
  365. {
  366.     char        reBuf[256];
  367.     char        edArgBuf[256];
  368.     char        *re;
  369.     int        c;
  370.     int        skip;
  371.     static char    *editor, *eidArg, *eidRightDel, *eidLeftDel;
  372.     static char    editbuf[128];
  373.  
  374.     if (editor == NULL && (editor = getenv("EDITOR")) == NULL) {
  375. #ifdef UNIX
  376.         char    *ucb_vi = "/usr/ucb/vi";
  377.         char    *bin_vi = "/usr/bin/vi";
  378.  
  379.         if (access(ucb_vi, 01) == 0)
  380.             editor = ucb_vi;
  381.         else if (access(bin_vi, 01) == 0)
  382.             editor = bin_vi;
  383.         else
  384.             editor = "/bin/ed";    /* YUCK! */
  385.         if (editor == ucb_vi || editor == bin_vi) {
  386.             eidArg = "+1;/%s/";
  387.             eidLeftDel = "\\<";
  388.             eidRightDel = "\\>";
  389.         }
  390. #endif
  391.     }
  392.     if (eidLeftDel == NULL) {
  393.         eidArg = getenv("EIDARG");
  394.         if ((eidLeftDel = getenv("EIDLDEL")) == NULL)
  395.             eidLeftDel = "";
  396.         if ((eidRightDel = getenv("EIDRDEL")) == NULL)
  397.             eidRightDel = "";
  398.     }
  399.  
  400.     lookId(name, argv);
  401.     savetty();
  402.     for (;;) {
  403.         printf("Edit? [y1-9^S/nq] "); fflush(stdout);
  404.         chartty();
  405.         c = (getchar() & 0177);
  406.         restoretty();
  407.         switch (TOLOWER(c))
  408.         {
  409.         case '/': case ('s'&037):
  410.             putchar('/');
  411.             /*FALLTHROUGH*/
  412.             if ((skip = skipToArgv(argv)) < 0)
  413.                 continue;
  414.             argv += skip;
  415.             goto editit;
  416.         case '1': case '2': case '3': case '4':
  417.         case '5': case '6': case '7': case '8': case '9':
  418.             putchar(c);
  419.             skip = c - '0';
  420.             break;
  421.         case 'y':
  422.             putchar(c);
  423.             /*FALLTHROUGH*/
  424.         case '\n':
  425.         case '\r':
  426.             skip = 0;
  427.             break;
  428.         case 'q':
  429.             putchar(c);
  430.             putchar('\n');
  431.             exit(0);
  432.         case 'n':
  433.             putchar(c);
  434.             putchar('\n');
  435.             return;
  436.         default:
  437.             putchar(c);
  438.             putchar('\n');
  439.             continue;
  440.         }
  441.  
  442.         putchar('\n');
  443.         while (skip--)
  444.             if (*++argv == NULL)
  445.                 continue;
  446.         break;
  447.     }
  448. editit:
  449.  
  450. #ifdef AMIGA
  451.     if (editor == NULL)
  452.     {
  453. /* let's assume getenv mallocs for multitasking */
  454.         printf("\nEditor? ");
  455.         if (!gets(editbuf))
  456.             goto cant_edit;
  457.         editor = editbuf;
  458.     }
  459. #endif
  460.     if (!Merging || (re = fileRE(name, eidLeftDel, eidRightDel)) == NULL)
  461.         sprintf(re = reBuf, "%s%s%s", eidLeftDel, name, eidRightDel);
  462.  
  463. #ifdef UNIX
  464.     switch (fork())
  465.     {
  466.     case -1:
  467.         fprintf(stderr, "%s: Cannot fork (%s)\n", MyName, uerror());
  468.         exit(1);
  469.     case 0:
  470.         argv--;
  471.         if (eidArg) {
  472.             argv--;
  473.             sprintf(edArgBuf, eidArg, re);
  474.             argv[1] = edArgBuf;
  475.         }
  476.         argv[0] = editor;
  477.         execv(editor, argv);
  478.         filerr("exec", editor);
  479.     default:
  480.         wait(0);
  481.         break;
  482.     }
  483. #endif UNIX
  484.  
  485. #ifdef AMIGA
  486. #ifdef LATTICE
  487.     {
  488. //        struct ProcID pid; /* from dos.h */
  489.  
  490.         argv--;
  491.         if (eidArg) {
  492.             argv--;
  493.             sprintf(edArgBuf, eidArg, re, argv[2]);
  494.             argv[1] = edArgBuf;
  495.         }
  496.         argv[0] = editor;
  497. #ifdef DEBUG
  498.         printf("Execing %s %s\n",editor,argv[1]);
  499. #endif
  500. //        if (forkv(editor,argv,NULL,&pid) == -1)
  501. //            goto cant_edit;
  502. //        wait(&pid);
  503.  
  504.         {
  505.             char *buffer = malloc(strlen(editor) + 1 + strlen(argv[1]) + 1);
  506.  
  507.             if(buffer)
  508.             {
  509.                 int result;
  510.  
  511.                 sprintf(buffer,"%s %s",editor,argv[1]);
  512.  
  513. //                printf("launch |%s|\n",buffer);
  514.  
  515.                 result = SystemTagList(buffer,NULL);
  516.  
  517.                 free(buffer);
  518.  
  519.                 if(result)
  520.                     goto cant_edit;
  521.             }
  522.             else
  523.                 goto cant_edit;
  524.         }
  525.     }
  526.     return;
  527.  
  528. cant_edit:
  529.     printf("Can't fork editor %s!\n",editor);
  530.     editor = NULL;    /* so it'll ask him */
  531. #else
  532.     printf("Fork code not written for non-Lattice!\n");
  533.     editor = NULL;    /* so it'll ask him */
  534. #endif LATTICE
  535. #endif AMIGA
  536. }
  537.  
  538. int
  539. skipToArgv(argv)
  540.     char        **argv;
  541. {
  542.     char        pattern[BUFSIZ];
  543.     int        count;
  544.  
  545.     if (gets(pattern) == NULL)
  546.         return -1;
  547.  
  548.     for (count = 0; *argv; count++, argv++)
  549.         if (strcpos(*argv, pattern))
  550.             return count;
  551.     return -1;
  552. }
  553.  
  554. int
  555. findPlain(arg, doit)
  556.     char        *arg;
  557.     void        (*doit)();
  558. {
  559.     static char    *buf, *bitArray;
  560.     int        size;
  561.  
  562.     if (searchName(arg) == 0)
  563.         return 0;
  564.     if (buf == NULL) {
  565.         buf = malloc(Idh.idh_bsiz);
  566.         bitArray = malloc(BitArraySize);
  567.     }
  568.     bzero(bitArray, BitArraySize);
  569.  
  570.     if ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) == 0)
  571.         return 0;
  572.     size++;
  573.     getsFF(&buf[size], IdFILE);
  574.     if (IGNORE_SOLO(buf))
  575.         return 0;
  576.  
  577.     vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  578.     (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  579.     return 1;
  580. }
  581.  
  582. int
  583. findAnchor(arg, doit)
  584.     register char    *arg;
  585.     void        (*doit)();
  586. {
  587.     static char    *buf, *bitArray;
  588.     int        count, size;
  589.     int        len;
  590.  
  591.     if (searchName(++arg) == 0)
  592.         return 0;
  593.  
  594.     if (buf == NULL) {
  595.         buf = malloc(Idh.idh_bsiz);
  596.         bitArray = malloc(BitArraySize);
  597.     }
  598.     bzero(bitArray, BitArraySize);
  599.  
  600.     len = strlen(arg);
  601.     count = 0;
  602.     while ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) > 0) {
  603.         size++;
  604.         getsFF(&buf[size], IdFILE);
  605.         if (IGNORE_SOLO(buf))
  606.             continue;
  607.         if (!strnequ(arg, ID_STRING(buf), len))
  608.             break;
  609.         vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  610.         if (!Merging) {
  611.             (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  612.             bzero(bitArray, BitArraySize);
  613.         }
  614.         count++;
  615.     }
  616.     if (Merging && count)
  617.         (*doit)(--arg, bitsToArgv(bitArray));
  618.  
  619.     return count;
  620. }
  621.  
  622. #if REGEX || RE_EXEC
  623. int
  624. findRegExp(re, doit)
  625.     char        *re;
  626.     void        (*doit)();
  627. {
  628.     static char    *buf, *bitArray;
  629.     int        count, size;
  630.     char        *reCompiled;
  631.  
  632. #ifdef REGEX
  633.     if ((reCompiled = regcmp(re, 0)) == NULL) {
  634.         fprintf(stderr, "%s: Syntax Error: %s\n", MyName, re);
  635.         return 0;
  636.     }
  637. #endif
  638. #ifdef RE_EXEC
  639.     if ((reCompiled = re_comp(re)) != NULL) {
  640.         fprintf(stderr, "%s: Syntax Error: %s (%s)\n", MyName, re, reCompiled);
  641.         return 0;
  642.     }
  643. #endif
  644.     fseek(IdFILE, Idh.idh_namo, 0);
  645.  
  646.     if (buf == NULL) {
  647.         buf = malloc(Idh.idh_bsiz);
  648.         bitArray = malloc(BitArraySize);
  649.     }
  650.     bzero(bitArray, BitArraySize);
  651.  
  652.     count = 0;
  653.     while ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) > 0) {
  654.         size++;
  655.         getsFF(&buf[size], IdFILE);
  656.         if (IGNORE_SOLO(buf))
  657.             continue;
  658. #ifdef REGEX
  659.         if (regex(reCompiled, ID_STRING(buf)) == NULL)
  660. #endif
  661. #ifdef RE_EXEC
  662.         if (!re_exec(ID_STRING(buf)))
  663. #endif
  664.             continue;
  665.         vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  666.         if (!Merging) {
  667.             (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  668.             bzero(bitArray, BitArraySize);
  669.         }
  670.         count++;
  671.     }
  672.     if (Merging && count)
  673.         (*doit)(re, bitsToArgv(bitArray));
  674.  
  675.     return count;
  676. }
  677. #endif
  678.  
  679. int
  680. findNumber(arg, doit)
  681.     char        *arg;
  682.     void        (*doit)();
  683. {
  684.     static char    *buf, *bitArray;
  685.     int        count, size;
  686.     register int    rdx = 0;
  687.     register int    val;
  688.     register bool    hitDigits = FALSE;
  689.  
  690.     if ((val = stoi(arg)) <= 7)
  691.         rdx |= RADIX_ALL;
  692.     else
  693.         rdx = radix(arg);
  694.     fseek(IdFILE, Idh.idh_namo, 0);
  695.  
  696.     if (buf == NULL) {
  697.         buf = malloc(Idh.idh_bsiz);
  698.         bitArray = malloc(BitArraySize);
  699.     }
  700.     bzero(bitArray, BitArraySize);
  701.  
  702.     count = 0;
  703.     while ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) > 0) {
  704.         size++;
  705.         getsFF(&buf[size], IdFILE);
  706.         if (hitDigits) {
  707.             if (!isdigit(*ID_STRING(buf)))
  708.                 break;
  709.         } else if (isdigit(*ID_STRING(buf)))
  710.             hitDigits = TRUE;
  711.  
  712.         if (!((Radix ? Radix : rdx) & radix(ID_STRING(buf)))
  713.         || stoi(ID_STRING(buf)) != val)
  714.             continue;
  715.         vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  716.         if (!Merging) {
  717.             (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  718.             bzero(bitArray, BitArraySize);
  719.         }
  720.         count++;
  721.     }
  722.     if (Merging && count)
  723.         (*doit)(arg, bitsToArgv(bitArray));
  724.  
  725.     return count;
  726. }
  727.  
  728. /*
  729.     Find identifiers that are non-unique within
  730.     the first `count' characters.
  731. */
  732. int
  733. findNonUnique(limit, doit)
  734.     int        limit;
  735.     void        (*doit)();
  736. {
  737.     static char    *buf1, *buf2, *bitArray;
  738.     register char    *old;
  739.     register char    *new;
  740.     register int    consecutive;
  741.     char        *cptmp;
  742.     int        itmp;
  743.     int        count, oldsize, newsize = 0;    /* added init, REJ */
  744.     char        *name;
  745.  
  746.     if (limit <= 1)
  747.         usage();
  748.  
  749.     fseek(IdFILE, Idh.idh_namo, 0);
  750.  
  751.     if (buf1 == NULL) {
  752.         buf1 = malloc(Idh.idh_bsiz);
  753.         buf2 = malloc(Idh.idh_bsiz);
  754.         bitArray = malloc(BitArraySize);
  755.     }
  756.     bzero(bitArray, BitArraySize);
  757.  
  758.     name = calloc(1, limit+2);
  759.     name[0] = '^';
  760.     old = buf1;
  761.     *ID_STRING(new = buf2) = '\0';
  762.     count = consecutive = 0;
  763.     while ((oldsize = fgets0(old, Idh.idh_bsiz, IdFILE)) > 0) {
  764.         oldsize++;
  765.         getsFF(&old[oldsize], IdFILE);
  766.         if (!(ID_FLAGS(old) & IDN_NAME))
  767.             continue;
  768.         cptmp = old; old = new; new = cptmp;
  769. /* DANGER! newsize is unitialized! REJ (make that was) */
  770.         itmp = oldsize; oldsize = newsize; newsize = itmp;
  771.         if (!strnequ(ID_STRING(new), ID_STRING(old), limit)) {
  772.             if (consecutive && Merging) {
  773.                 strncpy(&name[1], ID_STRING(old), limit);
  774.                 (*doit)(name, bitsToArgv(bitArray));
  775.             }
  776.             consecutive = 0;
  777.             continue;
  778.         }
  779.         if (!consecutive++) {
  780.             vecToBits(bitArray, &old[oldsize], Idh.idh_vecc);
  781.             if (!Merging) {
  782.                 (*doit)(ID_STRING(old), bitsToArgv(bitArray));
  783.                 bzero(bitArray, BitArraySize);
  784.             }
  785.             count++;
  786.         }
  787.         vecToBits(bitArray, &new[newsize], Idh.idh_vecc);
  788.         if (!Merging) {
  789.             (*doit)(ID_STRING(new), bitsToArgv(bitArray));
  790.             bzero(bitArray, BitArraySize);
  791.         }
  792.         count++;
  793.     }
  794.  
  795.     return count;
  796. }
  797.  
  798. int
  799. findApropos(arg, doit)
  800.     char        *arg;
  801.     void        (*doit)();
  802. {
  803.     static char    *buf, *bitArray;
  804.     int        count, size;
  805.  
  806.     fseek(IdFILE, Idh.idh_namo, 0);
  807.  
  808.     if (buf == NULL) {
  809.         buf = malloc(Idh.idh_bsiz);
  810.         bitArray = malloc(BitArraySize);
  811.     }
  812.     bzero(bitArray, BitArraySize);
  813.  
  814.     count = 0;
  815.     while ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) > 0) {
  816.         size++;
  817.         getsFF(&buf[size], IdFILE);
  818.         if (IGNORE_SOLO(buf))
  819.             continue;
  820.         if (strcpos(ID_STRING(buf), arg) == NULL)
  821.             continue;
  822.         vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  823.         if (!Merging) {
  824.             (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  825.             bzero(bitArray, BitArraySize);
  826.         }
  827.         count++;
  828.     }
  829.     if (Merging && count)
  830.         (*doit)(arg, bitsToArgv(bitArray));
  831.  
  832.     return count;
  833. }
  834.  
  835. /*
  836.     if string `s2' occurs in `s1', return a pointer to the
  837.     first match.  Ignore differences in alphabetic case.
  838. */
  839. char *
  840. strcpos(s1, s2)
  841.     char        *s1;
  842.     char        *s2;
  843. {
  844.     register char    *s1p;
  845.     register char    *s2p;
  846.     char        *s1last;
  847.  
  848.     for (s1last = &s1[strlen(s1) - strlen(s2)]; s1 <= s1last; s1++)
  849.         for (s1p = s1, s2p = s2; TOLOWER(*s1p) == TOLOWER(*s2p); s1p++)
  850.             if (*++s2p == '\0')
  851.                 return s1;
  852.     return NULL;
  853. }
  854.  
  855. /*
  856.     Convert the regular expression that we used to
  857.     locate identifiers in the id database into one
  858.     suitable for locating the identifiers in files.
  859. */
  860. char *
  861. fileRE(name0, leftDelimit, rightDelimit)
  862.     char        *name0;
  863.     char        *leftDelimit;
  864.     char        *rightDelimit;
  865. {
  866.     static char    reBuf[BUFSIZ];
  867.     register char    *name = name0;
  868.  
  869.     if (FindFunc == findNumber && Merging) {
  870.         sprintf(reBuf, "%s0*[Xx]*0*%d[Ll]*%s", leftDelimit, stoi(name), rightDelimit);
  871.         return reBuf;
  872.     }
  873.  
  874.     if (!isMagic(name) && name[0] != '^')
  875.         return NULL;
  876.  
  877.     if (name[0] == '^')
  878.         name0++;
  879.     else
  880.         leftDelimit = "";
  881.     while (*++name)
  882.         ;
  883.     if (*--name == '$')
  884.         *name = '\0';
  885.     else
  886.         rightDelimit = "";
  887.  
  888.     sprintf(reBuf, "%s%s%s", leftDelimit, name0, rightDelimit);
  889.     return reBuf;
  890. }
  891.  
  892. long
  893. searchName(name)
  894.     char        *name;
  895. {
  896.     long        offset;
  897.  
  898.     AnchorOffset = 0;
  899.     offset = (long)bsearch(name, (char *)(Idh.idh_namo-1), Idh.idh_endo-(Idh.idh_namo-1), 1, idCompare);
  900.     if (offset == 0)
  901.         offset = AnchorOffset;
  902.     if (offset == 0)
  903.         return 0;
  904.     fseek(IdFILE, offset, 0);
  905.     skipFF(IdFILE);
  906.     return ftell(IdFILE);
  907. }
  908.  
  909. int
  910. idCompare(key, offset)
  911.     register char    *key;
  912.     long        offset;
  913. {
  914.     register int    c;
  915.  
  916.     fseek(IdFILE, offset, 0);
  917.     skipFF(IdFILE);
  918.     getc(IdFILE);
  919.  
  920.     while (*key == (c = getc(IdFILE)))
  921.         if (*key++ == '\0')
  922.             return 0;
  923.     if (*key == '\0' && FindFunc == findAnchor)
  924.         AnchorOffset = offset;
  925.  
  926.     return *key - c;
  927. }
  928.  
  929. /*
  930.     Are there any magic Regular Expression meta-characters in name??
  931. */
  932. bool
  933. isMagic(name)
  934.     register char    *name;
  935. {
  936. #ifdef AMIGA
  937.     char        *magichar = "[]()%#?~*";
  938. #else
  939.     char        *magichar = "[]{}().*+^$";
  940. #endif
  941.     int        backslash = 0;
  942.  
  943. #ifdef AMIGA
  944.     while (*name) {
  945.         if (*name == '`')
  946.             name++, backslash++;
  947.         else if (strchr(magichar, *name))
  948.             return TRUE;
  949.         name++;
  950.     }
  951.     if (backslash)
  952.         while (*name) {
  953.             if (*name == '`')
  954.                 strcpy(name, name+1);
  955.             name++;
  956.         }
  957. #else
  958.     if (*name == '^')
  959.         name++;
  960.     while (*name) {
  961.         if (*name == '\\')
  962.             name++, backslash++;
  963.         else if (strchr(magichar, *name))
  964.             return TRUE;
  965.         name++;
  966.     }
  967.     if (backslash)
  968.         while (*name) {
  969.             if (*name == '\\')
  970.                 strcpy(name, name+1);
  971.             name++;
  972.         }
  973. #endif
  974.     return FALSE;
  975. }
  976.  
  977. char **
  978. bitsToArgv(bitArray)
  979.     char        *bitArray;
  980. {
  981.     static char    **argv;
  982.     struct idarg    *idArgs;
  983.     register char    **av;
  984.     register int    i;
  985. #define    ARGV1stPATH    3 /* available argv[] slots before first pathname */
  986.  
  987.     if (argv == NULL)
  988.         argv = (char **)malloc(sizeof(char *) * (Idh.idh_pthc + ARGV1stPATH + 2));
  989.  
  990.     av = argv + ARGV1stPATH;
  991.     for (idArgs = IdArgs, i = 0; i < Idh.idh_pthc; i++, idArgs++) {
  992.         if (!BITTST(bitArray, i))
  993.             continue;
  994.         if (idArgs->ida_flags & IDA_BLANK) {
  995.             printf("BOTCH: blank index!\n");
  996.             abort();
  997.         }
  998.         if (!(idArgs->ida_flags & IDA_ADJUST)) {
  999.             idArgs->ida_arg = strsav(spanPath(IdDir, idArgs->ida_arg));
  1000.             idArgs->ida_flags |= IDA_ADJUST;
  1001.         }
  1002.         *av++ = idArgs->ida_arg;
  1003.     }
  1004.     *av = NULL;
  1005.     return (argv + ARGV1stPATH);
  1006. }
  1007.